package cqrtplm.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.IterUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.hustcad.plm.pdm.common.util.CommonUtil;
import com.hustcad.plm.pdm.doc.service.TyplmDocumentService;
import com.hustcad.plm.pdm.doc.vo.DocDetails;
import com.hustcad.plm.pdm.ec.module.dto.ECObjData;
import com.hustcad.plm.pdm.ec.module.vo.ChgFormVO;
import com.hustcad.plm.pdm.ec.service.TyplmChgActRecordLinkService;
import com.hustcad.plm.pdm.ec.service.TyplmChgActivityService;
import com.hustcad.plm.pdm.ec.service.TyplmChgNoticeActivityLinkService;
import com.hustcad.plm.pdm.ec.service.TyplmEngineeringChangeService;
import com.hustcad.plm.pdm.flowbusiness.model.entity.FlowChgFormView;
import com.hustcad.plm.pdm.lifestage.service.TyplmCommonLifecycleService;
import com.hustcad.plm.pdm.partbom.service.TyplmPartDescribeLinkService;
import com.hustcad.plm.pdm.partbom.service.TyplmPartRelObjectService;
import com.hustcad.plm.pdm.partbom.vo.QueryDescribeObjVO;
import com.hustcad.plm.pdm.workflow.model.entity.WorkFlowContainerView;
import com.hustcad.plm.pdm.workflow.service.TyplmWorkFlowContainerService;
import com.ty.basic.constant.TableTypeConstrant;
import com.ty.basic.entity.CTyEntityBaseDO;
import com.ty.basic.entity.IdentifierEntity;
import com.ty.basic.service.snow.SnowflakeIdComponent;
import com.ty.basic.session.TyAccountContext;
import cqrtplm.constant.IpAddressConstant;
import cqrtplm.constant.RTPlmConstant;
import cqrtplm.dto.RtCfgStatusDTO;
import cqrtplm.dto.thirdPartyAPI.MomValueDTO;
import cqrtplm.dto.thirdPartyAPI.RestAdapterMomDTO;
import cqrtplm.entity.*;
import cqrtplm.mapper.*;
import cqrtplm.service.MomApiService;
import cqrtplm.service.RTChgListenerService;
import cqrtplm.vo.MomApiResponseVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigInteger;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class RTChgListenerServiceImpl implements RTChgListenerService {
    private static final int MAX_RETRY = 150; //设置最大重试次数防止死循环
    @Resource
    private TyplmWorkFlowContainerService typlmWorkFlowContainerService;
    @Resource
    private TyplmChgActivityService typlmChgActivityService;
    @Resource
    private TyplmDocumentService typlmDocumentService;
    @Resource
    private RTChangeMapper rtChangeMapper;
    @Resource
    private InterfaceLogRecordMapper interfaceLogRecordMapper;
    @Resource
    private SnowflakeIdComponent snowflakeIdComponent;
    @Resource
    private MomApiService momApiService;
    @Resource
    private RtCfgStatusInfoMapper rtCfgStatusInfoMapper;
    @Resource
    private TyplmCommonLifecycleService typlmCommonLifecycleService;
    @Resource
    private TyplmPartDescribeLinkService typlmPartDescribeLinkService;
    @Resource
    private RtChangeaffectFinishedbomMapper finishedbomMapper;
    @Resource
    private RtChangeaffectChangeobjectMapper changeobjectMapper;
    @Resource
    private TyplmEngineeringChangeService typlmEngineeringChangeService;
    @Resource
    private RtChangeaffectAssociatedbomMapper associatedbomMapper;
    @Resource
    private TyplmPartRelObjectService typlmPartRelObjectService;

    /**
     * 更新表单数据，主要用于处理变更通告流程中的特定逻辑。
     * <p>
     * 该方法会根据工作流容器ID获取详细信息，并判断是否属于变更通告流程（{@link FlowChgFormView}）。
     * 若是设计变更通知单（编号以"RTTJST"开头），则进一步查询相关BOM信息，
     * 提取工厂信息并更新到表单数据中。
     *
     * @param workFlowContainerId 工作流容器ID，用于获取对应的流程详情
     */
    @Override
    public void updateFormData(String workFlowContainerId) {
        WorkFlowContainerView workFlowContainerView = typlmWorkFlowContainerService.getWorkFlowContainerDetailByPrimaryKey(new BigInteger(workFlowContainerId));
        if (!Objects.isNull(workFlowContainerView) && workFlowContainerView instanceof FlowChgFormView) {
            // 判断当前流程是否为变更通告流程
            if (workFlowContainerView instanceof FlowChgFormView) {
                log.info("当前流程属于变更通告流程");
                FlowChgFormView flowChgFormView = (FlowChgFormView) workFlowContainerView;
                ChgFormVO chgFormVO = flowChgFormView.getChgFormVO();
                String changeNo = chgFormVO.getObjectNumber();

                // 只处理设计变更通知单（编号以 RTTJST 开头）
                if (StringUtils.isNotBlank(changeNo)) {
                    // 查询受影响的BOM信息，提取不重复的工厂列表
                    List<String> factorys = new ArrayList<>();
                    List<String> sourceFactorys = new ArrayList<>();
                    List<RtChangeaffectAssociatedbomDO> associatedbomDOList = associatedbomMapper.queryByChangeNoAndPartNo(changeNo, "");
                    if (CollUtil.isNotEmpty(associatedbomDOList)) {
                        List<String> associateList = associatedbomDOList.stream().map(RtChangeaffectAssociatedbomDO::getMadeVietnam).filter(Objects::nonNull).distinct().collect(Collectors.toList());
                        factorys.addAll(associateList.stream().flatMap(s -> Arrays.stream(s.split(","))) // 按逗号拆分并扁平化
                                .map(String::trim) // 去除前后空格
                                .filter(s -> !s.isEmpty()) // 过滤空字符串
                                .distinct() // 去重
                                .collect(Collectors.toList()));
                    }
                    if (changeNo.startsWith("RTTJJG")) {
                        // 如果存在工厂信息，则更新表单数据中的 ZJCD 字段
                        if (CollUtil.isNotEmpty(factorys)) {
                            String formData = chgFormVO.getFormData();
                            if (StringUtils.isNotBlank(formData)) {
                                JSONObject formDataJson = JSONObject.parseObject(formData);
                                JSONObject testObj = formDataJson.getJSONObject("testObj");
                                testObj.put("ZJCD", String.join(",", factorys));
                                formDataJson.put("testObj", testObj);
                                chgFormVO.setFormData(formDataJson.toJSONString());
                                this.typlmEngineeringChangeService.updateChgForm(chgFormVO);
                            }
                        }
                    } else if (changeNo.startsWith("RTTJST")) {
                        List<RtChangeaffectChangeobjectDO> changeobjectDOS = changeobjectMapper.queryByChangeNoAndPartNo(changeNo, "");
                        if (CollUtil.isNotEmpty(changeobjectDOS)) {
                            sourceFactorys = changeobjectDOS.stream().map(RtChangeaffectChangeobjectDO::getSourcefactory).filter(Objects::nonNull).distinct().collect(Collectors.toList());
                            sourceFactorys = sourceFactorys.stream().flatMap(s -> Arrays.stream(s.split(","))) // 按逗号拆分并扁平化
                                    .map(String::trim) // 去除前后空格
                                    .filter(s -> !s.isEmpty()) // 过滤空字符串
                                    .distinct() // 去重
                                    .collect(Collectors.toList());
                        }
                        List<RtChangeaffectFinishedbomDO> finishedbomDOS = finishedbomMapper.queryByChangeNoAndPartNo(changeNo, "");
                        if (CollUtil.isNotEmpty(finishedbomDOS)) {
                            List<String> finishedFactorys = finishedbomDOS.stream().map(RtChangeaffectFinishedbomDO::getProductioninvietnam).filter(Objects::nonNull).distinct().collect(Collectors.toList());
                            factorys.addAll(finishedFactorys.stream().flatMap(s -> Arrays.stream(s.split(","))) // 按逗号拆分并扁平化
                                    .map(String::trim) // 去除前后空格
                                    .filter(s -> !s.isEmpty()) // 过滤空字符串
                                    .distinct() // 去重
                                    .collect(Collectors.toList()));
                        }
                        if (CollUtil.isNotEmpty(factorys)) {
                            factorys = factorys.stream().flatMap(s -> Arrays.stream(s.split(","))) // 按逗号拆分并扁平化
                                    .map(String::trim) // 去除前后空格
                                    .filter(s -> !s.isEmpty()) // 过滤空字符串
                                    .distinct() // 去重
                                    .collect(Collectors.toList());
                            String formData = chgFormVO.getFormData();
                            if (StringUtils.isNotBlank(formData)) {
                                JSONObject formDataJson = JSONObject.parseObject(formData);
                                if (CollUtil.isNotEmpty(factorys)) {
                                    formDataJson.put("ZJCD", String.join(",", factorys));
                                }
                                if (CollUtil.isNotEmpty(sourceFactorys)) {
                                    formDataJson.put("LJHYD", String.join(",", sourceFactorys));
                                }
                                chgFormVO.setFormData(formDataJson.toJSONString());
                                this.typlmEngineeringChangeService.updateChgForm(chgFormVO);
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * 更新表单数据
     *
     * @param ecnId
     * @param objectType
     * @param tense
     * @param targetStatusKey
     */
    @Override
    public void setChangeObjectStatus(BigInteger ecnId, String objectType, String tense, String targetStatusKey) {
        WorkFlowContainerView workFlowContainerView = typlmWorkFlowContainerService.getWorkFlowContainerDetailByPrimaryKey(ecnId);
        if (!Objects.isNull(workFlowContainerView)) {
            TyAccountContext.setIgnoreAuth(true);
            // 判断当前流程是否为变更通告流程
            if (workFlowContainerView instanceof FlowChgFormView) {
                log.info("当前流程属于变更通告流程");
                FlowChgFormView flowChgFormView = (FlowChgFormView) workFlowContainerView;
                ChgFormVO chgFormVO = flowChgFormView.getChgFormVO();
                if ("变更前".equals(tense)) {
                    //变更前对象
                    List<ECObjData> beforeECObjDataVOS = chgFormVO.getEcObjDataVOS();
                    if (CollUtil.isNotEmpty(beforeECObjDataVOS)) {
                        List<ECObjData> cadDataVOS = beforeECObjDataVOS.stream().filter(ecObjData -> TableTypeConstrant.TY_CADDOC_OTYPE.contains(ecObjData.getOtype())).collect(Collectors.toList());
                        List<ECObjData> partDataVOS = beforeECObjDataVOS.stream().filter(ecObjData -> TableTypeConstrant.TY_PART_OTYPE.contains(ecObjData.getOtype())).collect(Collectors.toList());
                        List<ECObjData> docDataVOS = beforeECObjDataVOS.stream().filter(ecObjData -> TableTypeConstrant.TY_DOC_OTYPE.contains(ecObjData.getOtype())).collect(Collectors.toList());
                        List<CTyEntityBaseDO> entityList = new ArrayList<>();
                        if ("all".equals(objectType)) {
                            for (ECObjData ecObjData : beforeECObjDataVOS) {
                                String version=ecObjData.getVersion();
                                String number=ecObjData.getObjectNumber();
                                String otype=ecObjData.getOtype();
                                entityList.addAll(collectCTyEntityBaseDO(number,version,otype));
                            }
                        } else {
                            for (ECObjData ecObjData : partDataVOS) {
                                String type = ecObjData.getTypeDefName();
                                String version=ecObjData.getVersion();
                                String number=ecObjData.getObjectNumber();
                                if (type.equals(objectType)) {
                                    String otype=ecObjData.getOtype();
                                    entityList.addAll(collectCTyEntityBaseDO(number,version,otype));
                                    List<DocDetails> docDetails = this.typlmPartRelObjectService.queryPartRelatedDocInfo(ecObjData.getOid());
                                    if (CollUtil.isNotEmpty(docDetails)) {
                                        for (DocDetails docDetail : docDetails) {
                                            if (cadDataVOS.stream().anyMatch(item -> item.getOid().equals(docDetail.getOid()))) {
                                                version=docDetail.getVersion();
                                                number=docDetail.getObjectNumber();
                                                otype=docDetail.getOtype();
                                                entityList.addAll(collectCTyEntityBaseDO(number,version,otype));
                                            }
                                        }
                                    }
                                    List<IdentifierEntity> identifierEntityList = new ArrayList<>();
                                    identifierEntityList.add(new IdentifierEntity(ecObjData.getOid(), ecObjData.getOtype()));
                                    List<QueryDescribeObjVO> describeObjVOList = this.typlmPartDescribeLinkService.queryPartDescribeDoc(identifierEntityList);
                                    if (CollUtil.isNotEmpty(describeObjVOList)) {
                                        for (QueryDescribeObjVO describeObjVO : describeObjVOList) {
                                            if (cadDataVOS.stream().anyMatch(item -> item.getOid().equals(describeObjVO.getOid()))) {
                                                BigInteger oid =describeObjVO.getOid();
                                                otype=describeObjVO.getOtype();
                                                DocDetails docDetail = typlmDocumentService.queryDocDetails(oid,otype);
                                                version=docDetail.getVersion();
                                                number=docDetail.getObjectNumber();
                                                entityList.addAll(collectCTyEntityBaseDO(number,version,otype));
                                            }
                                            if (docDataVOS.stream().anyMatch(item -> item.getOid().equals(describeObjVO.getOid()))) {
                                                BigInteger oid =describeObjVO.getOid();
                                                otype=describeObjVO.getOtype();
                                                DocDetails docDetail = typlmDocumentService.queryDocDetails(oid,otype);
                                                version=docDetail.getVersion();
                                                number=docDetail.getObjectNumber();
                                                entityList.addAll(collectCTyEntityBaseDO(number,version,otype));
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        // 批量更新生命周期状态
                        if (CollUtil.isNotEmpty(entityList)) this.typlmCommonLifecycleService.batchUpdateEntityLifecycle(entityList, targetStatusKey, true, true);
                    }
                } else if ("变更后".equals(tense)) {
                    //变更后对象
                    List<ECObjData> afterECObjDataVOS = chgFormVO.getEcAffectVOS();
                    if (CollUtil.isNotEmpty(afterECObjDataVOS)) {
                        List<ECObjData> cadDataVOS = afterECObjDataVOS.stream().filter(ecObjData -> TableTypeConstrant.TY_CADDOC_OTYPE.contains(ecObjData.getOtype())).collect(Collectors.toList());
                        List<ECObjData> partDataVOS = afterECObjDataVOS.stream().filter(ecObjData -> TableTypeConstrant.TY_PART_OTYPE.contains(ecObjData.getOtype())).collect(Collectors.toList());
                        List<ECObjData> docDataVOS = afterECObjDataVOS.stream().filter(ecObjData -> TableTypeConstrant.TY_DOC_OTYPE.contains(ecObjData.getOtype())).collect(Collectors.toList());
                        List<CTyEntityBaseDO> entityList = new ArrayList<>();
                        if ("all".equals(objectType)) {
                            for (ECObjData ecObjData : afterECObjDataVOS) {
                                String version=ecObjData.getVersion();
                                String number=ecObjData.getObjectNumber();
                                CTyEntityBaseDO entity = CommonUtil.getEntity(new IdentifierEntity(ecObjData.getOid(), ecObjData.getOtype()));
                                entityList.add(entity);
                            }
                        } else {
                            for (ECObjData ecObjData : partDataVOS) {
                                String type = ecObjData.getTypeDefName();
                                String version=ecObjData.getVersion();
                                String number=ecObjData.getObjectNumber();
                                if (type.equals(objectType)) {
                                    CTyEntityBaseDO entity = CommonUtil.getEntity(new IdentifierEntity(ecObjData.getOid(), ecObjData.getOtype()));
                                    entityList.add(entity);
                                    List<DocDetails> docDetails = this.typlmPartRelObjectService.queryPartRelatedDocInfo(ecObjData.getOid());
                                    if (CollUtil.isNotEmpty(docDetails)) {
                                        for (DocDetails docDetail : docDetails) {
                                            if (cadDataVOS.stream().anyMatch(item -> item.getOid().equals(docDetail.getOid()))) {
                                                entity = CommonUtil.getEntity(new IdentifierEntity(ecObjData.getOid(), ecObjData.getOtype()));
                                                entityList.add(entity);
                                            }
                                        }
                                    }
                                    List<IdentifierEntity> identifierEntityList = new ArrayList<>();
                                    identifierEntityList.add(new IdentifierEntity(ecObjData.getOid(), ecObjData.getOtype()));
                                    List<QueryDescribeObjVO> describeObjVOList = this.typlmPartDescribeLinkService.queryPartDescribeDoc(identifierEntityList);
                                    if (CollUtil.isNotEmpty(describeObjVOList)) {
                                        for (QueryDescribeObjVO describeObjVO : describeObjVOList) {
                                            if (cadDataVOS.stream().anyMatch(item -> item.getOid().equals(describeObjVO.getOid()))) {
                                                entity = CommonUtil.getEntity(new IdentifierEntity(ecObjData.getOid(), ecObjData.getOtype()));
                                                entityList.add(entity);
                                            }
                                            if (docDataVOS.stream().anyMatch(item -> item.getOid().equals(describeObjVO.getOid()))) {
                                                entity = CommonUtil.getEntity(new IdentifierEntity(ecObjData.getOid(), ecObjData.getOtype()));
                                                entityList.add(entity);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        // 批量更新生命周期状态
                        if (CollUtil.isNotEmpty(entityList)) this.typlmCommonLifecycleService.batchUpdateEntityLifecycle(entityList, targetStatusKey, true, true);
                    }
                }
            }
        }
        TyAccountContext.setIgnoreAuth(false);
    }

    /**
     * 下发状态需求表数据到MOM
     *
     * @param workFlowContainerId
     */
    @Override
    public void sendStatusRequireToMOM(BigInteger workFlowContainerId) {
        if (workFlowContainerId == null) {
            return;
        }
        WorkFlowContainerView workFlowContainerView = typlmWorkFlowContainerService.getWorkFlowContainerDetailByPrimaryKey(workFlowContainerId);
        // 创建集合用于累积物料和BOM数据
        if (workFlowContainerView instanceof FlowChgFormView) {
            log.info("当前流程属于变更流程/发布流程");
            FlowChgFormView flowChgFormView = (FlowChgFormView) workFlowContainerView;
            ChgFormVO chgFormVO = flowChgFormView.getChgFormVO();
            String changeNo = chgFormVO.getObjectNumber();
            // 检查 getChgFormVO 是否为 null
            if (chgFormVO != null) {
                List<ECObjData> affectVOS = flowChgFormView.getChgFormVO().getEcAffectVOS();
                if (CollUtil.isNotEmpty(affectVOS)) {
                    for (ECObjData ecObjData : affectVOS) {
                        String viewName = ecObjData.getViewName();
                        String typeDefName = ecObjData.getTypeDefName();
                        String productCode = ecObjData.getObjectNumber();
                        if ("成品码".equals(typeDefName)) {
                            RtCfgStatusDTO dto = new RtCfgStatusDTO();
                            dto.setProductCode(productCode);
                            RtCfgStatusInfoDO statusInfoDO = rtCfgStatusInfoMapper.selectByStatusCode(dto);
                            this.sendSapAndMom(statusInfoDO);
                        }
                    }
                }
            }
        }
    }


    /**
     * 下发至sap,mom
     *
     * @param
     */
    private StringBuffer sendSapAndMom(RtCfgStatusInfoDO rtCfgStatusInfoDO) {
        //异常记录
        StringBuffer stringBuffer = new StringBuffer("");
        //下发MOM
        if (ObjectUtil.isNotEmpty(rtCfgStatusInfoDO)) {
            String moduleid = rtCfgStatusInfoDO.getModuleid();
            List<MomValueDTO> momValueList = rtCfgStatusInfoMapper.selectModulesubByMid(moduleid);
            if (IterUtil.isNotEmpty(momValueList)) {
                Map<String, String> aggregatedMap = momValueList.stream().filter(dto -> dto.getMapperName() != null && dto.getSelectValueName() != null).collect(Collectors.groupingBy(MomValueDTO::getMapperName, Collectors.mapping(MomValueDTO::getSelectValueName, Collectors.joining(","))));
                RestAdapterMomDTO restAdapterMomDTO = new RestAdapterMomDTO(aggregatedMap);
                MomApiResponseVO momApiResponseVO = momApiService.restInvoke(restAdapterMomDTO);
                if (!"S".equals(momApiResponseVO.getStatus())) {
                    stringBuffer.append("下发MOM失败:" + momApiResponseVO.getMessage());
                }
                //这里需要接口日志记录发送成功还是失败
                InterfaceLogRecordDO logRecordMOM = new InterfaceLogRecordDO(String.valueOf(snowflakeIdComponent.getInstance().nextId()), IpAddressConstant.MOM_CS_ZTKZ_CQ, "状态需求表下发MOM", "PLM->MOM", JSONUtil.toJsonStr(restAdapterMomDTO), JSONUtil.toJsonStr(momApiResponseVO), TyAccountContext.getUser().getName(), new Date());
                interfaceLogRecordMapper.insertInterfaceLogRecord(logRecordMOM);

            } else {
                stringBuffer.append("下发MOM失败,需求状态表中无MOM所需要的数据");
            }
        }
        return stringBuffer;
    }

    private List<CTyEntityBaseDO> collectCTyEntityBaseDO(String number, String version,String otype) {
        List<CTyEntityBaseDO> entityList = new ArrayList<>();
        if (number == null || version == null|| otype == null) {
            return entityList;
        }
        List<JSONObject> jsonObjects=null;
        if (TableTypeConstrant.TY_PART_OTYPE.equals(otype)){
            jsonObjects=rtChangeMapper.queryMaterialByCodeAndVersion(number,version,"",RTPlmConstant.VIEW_DESIGN);
        }else if (TableTypeConstrant.TY_DOC_OTYPE.equals(otype)){
            jsonObjects=rtChangeMapper.queryDrawDocByCodeAndVersion(RTPlmConstant.DOC_TABLE, RTPlmConstant.DOC_MASTER_TABLE, number, version);
        }else if (TableTypeConstrant.TY_CADDOC_OTYPE.equals(otype)){
            jsonObjects=rtChangeMapper.queryDrawDocByCodeAndVersion(RTPlmConstant.CADDOC_TABLE, RTPlmConstant.CADDOC_MASTER_TABLE, number, version);
        }
        if (CollUtil.isNotEmpty(jsonObjects)){
            for (JSONObject jsonObject : jsonObjects) {
                String oid = jsonObject.getString("OID");
                CTyEntityBaseDO entity = CommonUtil.getEntity(new IdentifierEntity(new BigInteger(oid), otype));
                entityList.add(entity);
            }
        }
        return entityList;
    }
}